<template>
	<view class="vi_styleController" :class="mainClass" :style="mainStyle"
		:hover-class="hoverClass?hoverClass:'vi_hover'"
		@click="onClick">
		<view class="vi_styleController_box" :class="{'vi_unTrans': !textHide||active}">
			<slot></slot>
		</view>
	</view>
</template>

<script>
	// 微信小程序对prop传入null值但定义类型不为null时会报警告
	// 进行computed转接过的prop参数，微信小程序初始传入均为null值，均会报警告
	export default {
		name:"viStyleController",
		options:{//样式穿透，微信须设置
			styleIsolation: "shared"
		},
		props:{
			//控制器名称（组件名）
			compName:{
				type:[String,null],
				default:""
			},
			size:{
				type:[String,null],
				default:""
			},
			type:{
				type:[String,null],
				default:""
			},
			//上色范围，背景、边框、文字。full为全部，可选border、background、text，多个须要数组
			control:{
				type:[String,Array,null],
				default:null
			},
			//自定义主题颜色，自定义颜色值
			color:{
				type:[String,null],
				default:""
			},
			//固定字体颜色，自定义颜色值，或inherit等，不进行校验
			textColor:{
				type:[String,null],
				default:""
			},
			//固定边框色，自定义颜色值，或transparent等，不进行校验
			borderColor:{
				type:[String,Array,null],
				default:""
			},
			//固定背景色，自定义颜色值，或transparent等，不进行校验
			backgroundColor:{
				type:[String,null],
				default:""
			},
			//焦点样式名，应用全局样式或本组件内定义样式  不能实现js写入自定义颜色
			hoverClass:{
				type:[String,null],
				default:""
			},
			//圆角，非数组时为全角，数组时定义从左上角开始顺时针4个方向角
			radius:{
				type:[Number,String,Array,null],
				default:0
			},
			//自定义宽度
			width:{
				type:[Number,String,null],
				default:""
			},
			//自定义高度
			height:{
				type:[Number,String,null],
				default:""
			},
			//边框宽，默认单位px。数组时定义从上开始顺时针4个方向边
			borderWidth:{
				type:[Number,String,Array,null],
				default:0
			},
			borderType:{
				type:[String,null],
				default:""
			},
			plain:{
				type:[Boolean,null],
				default:false
			},
			spaceInside:{
				type:[Number,String,Array,null],
				default:null
			},
			disabled:{
				type:[Boolean,null],
				default:false
			},
			readOnly:{
				type:[Boolean,null],
				default:false
			},
			//激活开关，激活主题色或自定义色
			active:{
				type:[Boolean,null],
				default:false
			},
			//未激活时内容透明
			textHide:{
				type:[Boolean,null],
				default:false
			},
			//固定边框，使边框无视禁用和激活，一直使用主题色或自定义色
			fixBorder:{
				type:[Boolean,null],
				default:false
			},
			inline:{
				type:[Boolean,null],
				default:false
			},
			//将尺寸类型改为borderBox
			borderBox:{
				type:[Boolean,null],
				default:false
			},
			//超出隐藏
			overHide:{
				type:[Boolean,null],
				default:false
			},
			//基础背景色，true为使用基础灰色
			basicBackground:{
				type:[Boolean,String,null],
				default:null
			},
			//基础边框色，true为使用基础灰色
			basicBorder:{
				type:[Boolean,String,null],
				default:null
			},
			//基础文字色，true为使用基础灰色
			basicText:{
				type:[Boolean,String,null],
				default:null
			},
			//阴影，同css box-shadow
			shadow:{
				type:[String,null],
				default:""
			},
			//固定触发点击，无论禁用与否
			forceClick:{
				type:[Boolean,null],
				default:false
			},
			//外框对齐居左
			alignLeft:{
				type:[Boolean,null],
				default:false
			}
		},
		data() {
			return {
				//方形圆角率，scss变量还有一个，须一致
				squareRate:0.2
			}
		},
		computed:{
			//默认参数内含，规避特殊使用的情况下，如组件嵌套且需要进行参数传递
			//由prop传入undefined、null等无效数据导致的，默认值丢失问题。只内含真值
			setting(){
				return {
					control: this.control ||["border","background","text"],
					borderType: this.borderType ||"solid"
				}
			},
			//是否开启背景
			useBg(){
				let control = this.setting.control;
				if(control=="background"
					||(this.$api.isArray(control)&&control.includes("background"))
					){
					return true
				}
				return false
			},
			//是否开启边框
			useBor(){
				let control = this.setting.control;
				if(control=="border"
					||(this.$api.isArray(control)&&control.includes("border"))
					){
					return true
				}
				return false
			},
			//是否开启文字
			useTxt(){
				let control = this.setting.control;
				if(control=="text"
					||(this.$api.isArray(control)&&control.includes("text"))
					){
					return true
				}
				return false
			},
			//设置镂空、不启用背景、未激活均为镂空
			isPlain(){
				if(this.plain||!this.useBg||!this.active){
					return true
				}
				return false
			},
			//是否使用背景主题
			//前提条件：开启背景，且有主题，且无自定色值，且无固定背景色
			//正常条件：需激活，且非镂空，且非禁用
			themeBg(){
				if(this.useBg
					&&this.type
					&&!this.$api.isColor(this.color)
					&&!this.backgroundColor
					&&this.active
					&&!this.plain
					&&!this.disabled
					){
					return true
				}
				return false
			},
			//是否使用边框主题
			//前提条件：开启边框，且有主题，且无自定色值
			//正常条件：需激活，且（非禁用，或固定显示）
			themeBor(){
				if(this.useBor
					&&this.type
					&&!this.$api.isColor(this.color)
					// &&!this.borderColor 为兼容四个方向不完全的固定边框色，保留主题边框色作为底色
					&&this.active
					&&(!this.disabled||this.fixBorder)
					){
					return true
				}
				return false
			},
			//是否使用文字主题
			//前提条件：开启文字，且有主题，且无自定色值，且无固定文字色
			//正常条件：需激活，且非禁用
			themeTxt(){
				if(this.useTxt
					&&this.type
					&&!this.$api.isColor(this.color)
					&&!this.textColor
					&&this.active
					&&!this.disabled
					){
					return true
				}
				return false
			},
			//需要背景style控制(自定色)
			//前提条件：开启背景且有自定色，且无固定背景色
			//正常条件：需激活，且非禁用、且非镂空
			customBg(){
				if(this.useBg
					&&this.$api.isColor(this.color)
					&&!this.backgroundColor
					&&this.active
					&&!this.disabled
					&&!this.plain
					){
					return true
				}
				return false
			},
			//需要边框style控制(自定色)
			//前提条件：开启边框且有自定色，且无固定边框色
			//正常条件：需激活，且（非禁用或固定显示）
			customBor(){
				if(this.useBor
					&&this.$api.isColor(this.color)
					&&!this.borderColor
					&&this.active
					&&(!this.disabled||this.fixBorder)
					){
					return true
				}
				return false
			},
			//需要文字style控制(自定色)
			//前提条件：开启文字，且非禁用
			//正常条件：固定文字色，或（激活且有自定色且(镂空或未启用背景)）
			customTxt(){
				if(this.useTxt
					&&!this.disabled
					&&(this.textColor||(this.active&&this.$api.isColor(this.color)&&(this.plain||!this.useBg)))
					){
					return true
				}
				return false
			},
			//需要文字反色style控制(自定色)
			//前提条件：开启文字，且非镂空，且激活
			//分支1：有主题，且禁用
			//分支2：有自定色
			txtInverse(){
				if(this.useTxt
					&&!this.isPlain
					&&this.active
					&&( (this.type&&this.disabled)||this.$api.isColor(this.color) )
					){
					return true
				}
				return false
			},
			//基础背景色
			//前提条件，开启背景，且开启基础背景色
			//正常条件：无主题无自定色，或未激活，或镂空
			basicBg(){
				if(this.useBg
					&&this.basicBackground
					&&( (!this.type&&!this.$api.isColor(this.color))||!this.active||this.plain )
					){
					return this.basicBackground==true? "css": "style"
				}
				return false
			},
			//基础边框色
			//前提条件，开启边框，且开启基础边框色
			//分支1，无主题，且无自定色
			//分支2：非激活，且非禁用
			basicBor(){
				if(this.useBor
					&&this.basicBorder
					&&( (!this.type&&!this.$api.isColor(this.color))
						||(!this.active&&!this.disabled) )
					){
					return this.basicBorder==true? "css": "style"
				}
				return false
			},
			//基础文字色
			//前提条件，开启文字，且开启基础文字色
			//分支1：无主题且无自定色
			//分支2：未激活，且非禁用
			basicTxt(){
				if(this.useTxt
					&&this.basicText
					&&( (!this.type&&!this.$api.isColor(this.color))
						||(!this.active&&!this.disabled) )
					){
					return this.basicText==true? "css": "style"
				}
				return false
			},
			//背景样式style结果
			backgroundStyle(){
				if(this.backgroundColor){
					return "background:"+ this.backgroundColor +";"
				}else if(this.customBg){
					return "background:"+ this.color +";"
				}else if(this.basicBg=="style"){
					return "background:"+ this.basicBackground +";"
				}
				return ""
			},
			//边框样式style结果，追加阴影设置
			borderStyle(){
				let res={};
				let borderWidth = this.borderWidth ||0;
				if(this.$api.isArray(borderWidth)){
					let bt = borderWidth[0] ||0,
						br = borderWidth[1] ||0,
						bb = borderWidth[2] ||0,
						bl = borderWidth[3] ||0;
					bt = this.$api.isNumber(bt, true)? bt +"px" :bt;
					br = this.$api.isNumber(br, true)? br +"px" :br;
					bb = this.$api.isNumber(bb, true)? bb +"px" :bb;
					bl = this.$api.isNumber(bl, true)? bl +"px" :bl;
					res["border-width"] = `${bt} ${br} ${bb} ${bl}`;
				}else if(this.$api.isNumber(borderWidth, true)){
					res["border-width"] = borderWidth +"px"
				}else{
					res["border-width"] = borderWidth
				}
				let borderColor = this.borderColor;
				if(borderColor){
					if(this.$api.isArray(borderColor)){
						if(borderColor[0]){
							res["border-top-color"] = borderColor[0]
						}
						if(borderColor[1]){
							res["border-right-color"] = borderColor[1]
						}
						if(borderColor[2]){
							res["border-bottom-color"] = borderColor[2]
						}
						if(borderColor[3]){
							res["border-left-color"] = borderColor[3]
						}
					}else{
						res["border-color"] = borderColor
					}
				}else if(this.customBor){
					res["border-color"] = this.color
				}else if(this.basicBor=="style"){
					res["border-color"] = this.basicBorder
				}
				
				res["border-style"] = this.setting.borderType;
				if(this.borderBox){
					res["box-sizing"] = "border-box"
				}
				if(this.shadow){
					res["box-shadow"] = this.shadow
				}
				return this.$api.objToStr(res)
			},
			//文字样式style结果
			textStyle(){
				//以固定文字颜色为优先
				if(this.customTxt){
					if(this.textColor){
						return "color:"+ this.textColor +";"
					}else{
						return "color:"+ this.color +";"
					}
				}else if(this.basicTxt=="style"){
					return "color:"+ this.basicText +";"
				}else if(this.textHide&&!this.active){//开启了未激活隐藏文字且处于未激活，返回透明
					return "color:transparent;"
				//无各种文字主题色及基础文字色，或未激活且未禁用未隐藏，返回继承色(初始默认透明)
				}else if(!this.useTxt||!this.type||(!this.active&&!this.disabled&&!this.readOnly)){
					return "color:inherit;"
				}
				return ""
			},
			//圆角样式style结果
			radiusStyle(){
				let res={};
				let radius = this.radius ||0;
				if(this.$api.isArray(radius)){
					let lt = radius[0] ||0,
						rt = radius[1] ||0,
						rb = radius[2] ||0,
						lb = radius[3] ||0;
					res["border-radius"] = `${lt} ${rt} ${rb} ${lb}`;
				}else if(radius=="circle"||radius=="square"){
					//仅处理自定义宽高，非自定义则使用主题样式处理。取短边做圆角
					let splitW=[], splitH=[];
					if(this.width){
						if(/^[\d/.]+[a-zA-Z]*$/.test(this.width)){//格式校验，数字带字母的进行转换
							splitW=this.$api.splitUnit(this.width)
						}
					}
					if(this.height){
						if(/^[\d/.]+[a-zA-Z]*$/.test(this.height)){//格式校验，数字带字母的进行转换
							splitH=this.$api.splitUnit(this.height)
						}
					}
					if(splitW[0] && splitH[0]){
						//宽高单位不对等，取高做圆角
						if(splitW[1]!=splitH[1] || splitW[0]>splitH[0]){
							res["border-radius"] = `${radius=="circle"? splitH[0]/2 : splitH[0] * this.squareRate}${splitH[1]}`
						}else if(!["%","vh"].includes(splitW[1])){
							res["border-radius"] = `${radius=="circle"? splitW[0]/2 : splitW[0] * this.squareRate}${splitW[1]}`
						}
					}else if(splitW[0]&&!["%","vh"].includes(splitW[1])){
						res["border-radius"] = `${radius=="circle"? splitW[0]/2 : splitW[0] * this.squareRate}${splitW[1]}`
					}else if(splitH[0]&&!["%","vh"].includes(splitH[1])){
						res["border-radius"] = `${radius=="circle"? splitH[0]/2 : splitH[0] * this.squareRate}${splitH[1]}`
					}
				}else{
					res["border-radius"] = radius
				}
				return this.$api.objToStr(res)
			},
			//宽度、边距样式style结果
			widthStyle(){
				let res = "",
					spaceInside = this.spaceInside;
				res += this.inline? `display:inline-flex;` :"";
				res += this.width? `width:${this.width};` :"";
				if(this.$api.isValue(spaceInside)){
					res += this.$api.isArray(spaceInside)? `padding:${spaceInside.join(" ")};` :`padding:${spaceInside};`
				}
				return res
			},
			//高度样式style结果
			heightStyle(){
				return this.height? `height:${this.height};` :""
			},
			//总样式style集合
			mainStyle(){
				return this.widthStyle + this.heightStyle + this.borderStyle + this.backgroundStyle + this.textStyle + this.radiusStyle
			},
			mainClass(){
				let res="";
				res += this.compName? `vi_${this.compName} ` :"";
				res += this.size? `vi_${this.size} ` :"";
				res += this.type? `vi_${this.type} ` :"";
				res += this.isPlain? "vi_plain " :"";//未使用背景当做镂空
				res += this.active? "vi_active " :"vi_unActive ";
				res += this.readOnly? "readOnly " :"";
				
				res += this.themeBg? "vi_themeBg " :"";
				res += this.themeBor? "vi_themeBor " :"";
				res += this.themeTxt? "vi_themeTxt " :"";
				
				res += this.txtInverse? "vi_inverse " :"";
				res += this.basicBg=="css"? "vi_basic_background " :"";
				res += this.basicBor=="css"? "vi_basic_border " :"";
				res += this.basicTxt=="css"? "vi_basic_text " :"";
				res += this.overHide? "vi_overHide " :"";
				if(this.disabled){
					res += "disabled ";
					res += (this.useBg && !this.plain && this.active)? "vi_disBg " :"";
					res += (this.useBor && !this.fixBorder)? "vi_disBor " :"";
					res += this.useTxt? "vi_disTxt " :"";
				}else if(this.readOnly){
					res += (this.useBg && !this.plain && this.active)? "vi_readBg " :"";
					res += (this.useBor && !this.fixBorder)? "vi_readBor " :"";
					res += (this.useTxt && (this.isPlain || this.textColor))? "vi_readTxt " :"";
				}
				
				res += this.inline? "vi_auto " :"";
				res += !this.alignLeft? "vi_autoCenter " :"";
				//主题圆角
				if(this.radius=="circle"){
					res += "vi_circle "
				}else if(this.radius=="square"){
					res += "vi_square "
				}
				return res
			}
		},
		methods:{
			onClick(e){
				if(!this.forceClick&&(this.disabled||this.readOnly)){
					return
				}
				this.$emit("click", e)
			}
		}
	}
</script>

<style lang="scss">
$transition:.3s;
.vi_styleController{
	width: 100%;
	display: flex;
	justify-content: center;
	align-items: center;
	border-color: transparent;
	transition: $transition;
	text-align: initial;
	color:transparent;//初始透明，解决js样式设置滞后导致文字从黑色渐变
	&.vi_autoCenter{
		margin: auto;
	}
	&.vi_auto{
		width: auto;
	}
	.vi_styleController_box{
		width: 100%;
		height: 100%;
		display: flex;
		align-items: center;
		justify-content: center;
		opacity: 1;
		transition: opacity $transition;
		opacity: 0;
		&.vi_unTrans{//反向设置回避初始化残留
			opacity: 1;
		}
	}
	&.vi_overHide{
		overflow: hidden;
	}
	&.vi_inverse{
		color: $vi-txtColor-inverse;
	}
	&.vi_basic_background{
		background: $vi-borColor-default;
	}
	&.vi_basic_border{
		border-color: $vi-borColor-default;
	}
	&.vi_basic_text{
		color: $vi-borColor-default;
	}
	&.disabled{
		&.vi_disBg{
			background: $vi-color-disable;
		}
		&.vi_disBor{
			border-color: $vi-color-disable;
			&.vi_hover{
				border-color: $vi-color-error;
			}
		}
		&.vi_disTxt{
			color: $vi-color-disable;
			&.vi_inverse{
				color: $vi-txtColor-inverse;
			}
			&.vi_hover.vi_plain,
			&.vi_hover.vi_unActive{
				color: $vi-color-error;
			}
		}
	}
	&.readOnly{
		&.vi_readTxt{
			color: inherit;
		}
		&.vi_hover{
			&.vi_readBor{
				border-color: $vi-color-error;
			}
			&.vi_readTxt.vi_plain,
			&.vi_readTxt.vi_unActive{
				color: $vi-color-error;
			}
		}
	}
}

//主题样式
@import "./vi-style-controller.scss";
</style>
